﻿using Casamiel.Domain.Entity;
using Casamiel.Domain;
using Smooth.IoC.UnitOfWork.Abstractions;
using Smooth.IoC.UnitOfWork.Interfaces;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Enyim.Caching;
using Microsoft.Extensions.Options;
using Casamiel.Common;

namespace Casamiel.Application
{
    /// <summary>
    /// Member card service.
    /// </summary>
    public class MemberCardService : IMemberCardService
    {
        private readonly IMemberCardRepository _membercardRepostitory;
        private readonly IMemcachedClient _memcachedClient;
        private readonly string _memcachedPre = "";
        private readonly bool _cacheEnable;
        private readonly int _cacheSeconds = 720;
        public MemberCardService(IOptionsSnapshot<CasamielSettings> snapshot, IMemberCardRepository memberRepostitory, IMemcachedClient memcachedClient)//,ICasaMielSession session)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }
            _memcachedPre = snapshot.Value.MemcachedPre;
            _cacheEnable = snapshot.Value.CacheEnable;
            _membercardRepostitory = memberRepostitory;
            _memcachedClient = memcachedClient;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TSession"></typeparam>
        /// <param name="card"></param>
        public async Task AddAsync<TSession>(MemberCard card) where TSession : class, ISession
        {
            if (card == null)
            {
                throw new ArgumentNullException(nameof(card));
            }

            await _membercardRepostitory.SaveAsync<TSession>(card).ConfigureAwait(false);
            if (_cacheEnable)
            {
                var _cacheKey = _memcachedPre + Constant.MYCARDS_PREFIX + card.Mobile;
                await _memcachedClient.RemoveAsync(_cacheKey).ConfigureAwait(false);
            }
        }

        /// <summary>
        /// Adds the async.
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="cardNO">Card no.</param>
        /// <param name="mobile">Mobile.</param>
        /// <param name="cardtype">Cardtype.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async Task AddAsync<TSession>(string cardNO, string mobile, string cardtype) where TSession : class, ISession
        {
            var card = new MemberCard { CardType = cardtype,IsBind=true,State=1, CardNO = cardNO, Mobile = mobile, BindTime = DateTime.Now, CreateTime = DateTime.Now };
            await _membercardRepostitory.SaveAsync<TSession>(card).ConfigureAwait(false);
            if (_cacheEnable)
            {
                var _cacheKey = _memcachedPre + Constant.MYCARDS_PREFIX + card.Mobile;
                await _memcachedClient.RemoveAsync(_cacheKey).ConfigureAwait(false);
            }
        }
        //public async Task<bool> GetCardListAsyncByMobile(MemberCard entity)
        //{
        //	return await _membercardRepostitory.UpdateAsync<ICasaMielSession>(entity);
        //}

        public async Task<MemberCard> FindAsync<TSession>(string cardno, string mobile) where TSession : class, ISession
        {
            return await _membercardRepostitory.FindAsync<TSession>(cardno, mobile).ConfigureAwait(false);
        }
        /// <summary>
        /// Finds the async by card card no.
        /// </summary>
        /// <returns>The async by card card no.</returns>
        /// <param name="cardno">Cardno.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async   Task<MemberCard> FindAsync<TSession>(string cardno) where TSession : class, ISession
        {
            return await _membercardRepostitory.GetKeyAsync<TSession>(cardno).ConfigureAwait(false);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TSession"></typeparam>
        /// <param name="CardNO"></param>
        /// <returns></returns>
        public async Task<bool> DeleteByCardNO<TSession>(string CardNO) where TSession : class, ISession
        {
            return await _membercardRepostitory.DeleteByCardNO<TSession>(CardNO).ConfigureAwait(false);
        }

        public async Task<MemberCard> FindAsync<TSession>(string mobile, bool isGiftCard) where TSession : class, ISession
        {
            return await _membercardRepostitory.FindAsync<TSession>(mobile,isGiftCard).ConfigureAwait(false);
        }

        /// <summary>
        /// 绑定的卡
        /// </summary>
        /// <param name="mobile"></param>
        /// <returns></returns>
        public async Task<MemberCard> GetBindCardAsync<TSession>(string mobile) where TSession : class, ISession
        {
            return await _membercardRepostitory.GetBindCardAsync<TSession>(mobile).ConfigureAwait(false);
        }
        //public async	 Task<List<MemberCard>> GetCardListAsyncByMobile<TSession>(string mobile) where TSession:class,ISession
        //{
        //	return await _membercardRepostitory.GetCardListAsyncByMobile<ISession>(mobile);
        //}

        public async Task<bool> UpdateAsync<TSession>(MemberCard entity) where TSession : class, ISession
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }
            var success = await _membercardRepostitory.UpdateAsync<TSession>(entity).ConfigureAwait(false);
            if (_cacheEnable && success)
            {
                var _cacheKey = _memcachedPre + Constant.MYCARDS_PREFIX + entity.Mobile;
                await _memcachedClient.RemoveAsync(_cacheKey).ConfigureAwait(false);
            }
            return success;
        }
        /// <summary>
        /// Res the bind async.
        /// </summary>
        /// <returns>The bind async.</returns>
        /// <param name="cardNO">Card no.</param>
        /// <typeparam name="TSession">The 1st type parameter.</typeparam>
        public async Task<bool>   ReBindAsync<TSession>(string cardNO) where TSession : class, ISession{
            var entity = await _membercardRepostitory.GetKeyAsync<TSession>(cardNO).ConfigureAwait(false);
            if(entity==null){
                return false;
            }
            entity.IsBind = true;
            entity.BindTime = DateTime.Now;
            var success = await _membercardRepostitory.UpdateAsync<TSession>(entity).ConfigureAwait(false);
            if (_cacheEnable && success)
            {
                var _cacheKey = _memcachedPre + Constant.MYCARDS_PREFIX + entity.Mobile;
                await _memcachedClient.RemoveAsync(_cacheKey).ConfigureAwait(false);
            }
            return success;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TSession"></typeparam>
        /// <param name="mobile"></param>
		/// <param name="hasCached"></param>
        /// <returns></returns>
        public async Task<List<MemberCard>> GetListAsync<TSession>(string mobile,bool hasCached) where TSession : class, ISession
        {
            if (_cacheEnable && hasCached==true)
            {
                var _cacheKey = _memcachedPre + Constant.MYCARDS_PREFIX + mobile;
                var cardlist = await _memcachedClient.GetValueAsync<List<MemberCard>>(_cacheKey).ConfigureAwait(false);
                if (cardlist == null)
                {
                    cardlist = await _membercardRepostitory.GetListAsync<TSession>(mobile).ConfigureAwait(false);
                    if (cardlist != null)
                    {
                        await _memcachedClient.AddAsync(_cacheKey, cardlist, _cacheSeconds).ConfigureAwait(false);
                    }
                    return cardlist;
                }
            }
            return await _membercardRepostitory.GetListAsync<TSession>(mobile).ConfigureAwait(false);
        }

        public async Task<List<MemberCard>> GetListAsny<TSession>(string a, string b) where TSession : class, ISession
        {
            return await _membercardRepostitory.GetListAsny<TSession>(a, b).ConfigureAwait(false);
        }

 
    }
}
